#ifndef __CZF_VAR_ARRAY_T_H__
#define __CZF_VAR_ARRAY_T_H__

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "errordef.h"
#include "typedefs.h"

template <class T> class CVarArrayT
{
public:
   CVarArrayT(int nInitCount)
   {
      assert (nInitCount >= 0);
      m_nCount = nInitCount;
      if (nInitCount > 0) {
         m_pArray = (T*)malloc(sizeof(T)*nInitCount);
         if (!m_pArray) {
            fprintf (stderr, "%s, %d, CVarArrayT, cannot allocate memory.\n", __FILE__, __LINE__);
            m_nCount = 0;
            return;
         }
         memset(m_pArray, 0, sizeof(T)*nInitCount);
      } else {
         m_pArray = NULL;
      }
   }
   virtual ~CVarArrayT()
   {
      if (m_pArray) {
         free(m_pArray);
      }
   }

   int32 Resize(int nCount)
   {
      assert (nCount >= 0);
      
      if (m_nCount == nCount) {
         return 0;
      }
      
      int nMin = m_nCount > nCount ? nCount : m_nCount;
      if (nCount > 0) {
         T* pTmp = (T*)malloc(sizeof(T)*nCount);
         if (!pTmp) {
            fprintf (stderr, "%s, %d, Resize, cannot allocate memory.\n", __FILE__, __LINE__);
            return E_INSUFFICIENT_MEMORY;
         }
         memset(pTmp, 0, sizeof(T)*nCount);
         if (m_pArray) {
            memcpy(pTmp, m_pArray, sizeof(T)*nMin);
            free(m_pArray);
         } else {
            /* !m_pArray */
            assert (m_nCount == 0);
         }
         m_pArray = pTmp;  
         m_nCount = nCount;
      } else {
         /* nCount == 0 */
         assert (nCount == 0);
         if (m_pArray) {
            free (m_pArray);
            m_pArray = NULL;
         } else {
            /* !m_pArray */
            assert (m_nCount == 0);
         }
         m_nCount = 0;
      }
      return 0;
   }
   
   int GetCount()
   {
      assert (m_nCount >= 0);
      return m_nCount;
   }

   void RemoveAt(int nIdx)
   {
      assert (nIdx < m_nCount);
      assert (m_pArray);
      
      memmove(m_pArray+nIdx, (m_pArray+nIdx+1), sizeof(T)*(m_nCount-nIdx-1));
      return;
   }
      
   
   T* Detach()
   {
      T* pArray = m_pArray;
      m_pArray = NULL;
      m_nCount = 0;
      return pArray;   
   }
        
   T& operator [](int nIdx)
   {
      assert (nIdx < m_nCount);
      assert (nIdx >= 0);
      assert (m_pArray);
      
      return (m_pArray[nIdx]);
   }
   
   T* GetArrayPtr()
   {
      return m_pArray;
   }
   
protected:
   int m_nCount;
   T* m_pArray;   
};
#endif // __CZF_VAR_ARRAY_H__
